#include <Python.h>
#include <numpy/arrayobject.h>

#include <boost/tuple/tuple.hpp>
#include <kuai/misc/typedef.hpp>
#include <kuai/mol/pbc.hpp>
#include <kuai/sim/energy.hpp>

#ifndef _KUAISUAN_PYTOOL_HPP_
#define _KUAISUAN_PYTOOL_HPP_

namespace kuai { namespace suan {

extern bool getPBC(PyObject* model, const char szname[], kuai::PBC** result);
inline bool getPBC(PyObject* model, kuai::PBC** result) {
	return getPBC(model, "pbc", result);
}

boost::tuple<PyObject*, kuai::RealNumber*, size_t> getRealArray(PyObject* model, const char szAttrName[]);
std::pair<kuai::RealNumber*, size_t> getRealArray(PyObject* obj);

boost::tuple<PyObject*, kuai::XYZ*, size_t> getXYZArray(PyObject* model, const char szAttrName[]);
std::pair<kuai::XYZ*, size_t> getXYZArray(PyObject* obj);

boost::tuple<PyObject*, kuai::Index*, size_t> getIndexArray(PyObject* model, const char szAttrName[]);
std::pair<kuai::Index*, size_t> getIndexArray(PyObject* obj);

std::pair<PyObject*, kuai::RealNumber*> newRealArray(PyObject* model, const char szAttrName[], size_t n);
std::pair<PyObject*, kuai::RealNumber*> newRealArray(npy_intp n, kuai::RealNumber v0);
std::pair<PyObject*, kuai::RealNumber*> newRealArray(npy_intp n);

std::pair<PyObject*, kuai::XYZ*> newXYZArray(PyObject* model, const char szAttrName[], size_t n);
std::pair<PyObject*, kuai::XYZ*> newXYZArray(npy_intp n, const kuai::XYZ& v0);
std::pair<PyObject*, kuai::XYZ*> newXYZArray(npy_intp n);

class PythonControl;

extern bool convertToEnergySet(PyObject* model, PyObject* efunc, kuai::EnergySet& result);
extern bool convertToControlSet(PyObject* model, EnergySet& efunc, PyObject* controls, kuai::ControlSet& result, std::vector<PythonControl*>&);


#ifdef USE_DOUBLE
	enum {
		NPY_REAL_TYPE = NPY_DOUBLE,
		NPY_INDEX_TYPE = NPY_UINT
	};
#else
	enum {
		NPY_REAL_TYPE = NPY_FLOAT,
		NPY_INDEX_TYPE = NPY_USHORT
	};	
#endif

} }

#endif
